package com.github.kezhenxu94.crawler.source.rss;

import com.github.kezhenxu94.data.source.Source;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import java.net.URL;
import java.net.URLConnection;
import java.text.SimpleDateFormat;
import java.util.Map;
import java.util.concurrent.*;

/**
 * Created by kezhenxu on 1/7/17.
 *
 * @author kezhenxu (kezhenxu94@163.com)
 */
public class Rss2Source implements Source<Rss2Item> {

    protected Map<String, String> rssDateFormat;

    protected ExecutorService executor;
    protected volatile boolean isRunning;
    protected BlockingQueue<Rss2Item> queue;

    @Override
    public void setup() throws Exception {
        this.executor = Executors.newSingleThreadExecutor();
        this.queue = new LinkedBlockingQueue<>();
    }

    @Override
    public void start() throws Exception {
        isRunning = true;
        executor.execute(() -> rssDateFormat.entrySet().forEach(entry -> {
            try {
                URL url = new URL(entry.getKey());

                getLogger().debug("Fetching url {}. ", url);

                URLConnection connection = url.openConnection();
                connection.setRequestProperty("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.98 Safari/537.36");

                SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
                Rss2Handler handler = new Rss2Handler();
                handler.setDateFormat(new SimpleDateFormat(entry.getValue()));
                parser.parse(connection.getInputStream(), handler);
                Rss2Channel channel = handler.getChannel();
                channel.getItems().forEach(item -> queue.offer(item));
            } catch (Exception e) {
                getLogger().error(e.getMessage(), e);
            }
        }));
    }

    @Override
    public void close() throws Exception {
        isRunning = false;
        while (isRunning()) {
            TimeUnit.MILLISECONDS.sleep(500L);
        }
        executor.awaitTermination(5L, TimeUnit.SECONDS);
    }

    @Override
    public boolean isRunning() {
        return isRunning || !queue.isEmpty();
    }

    @Override
    public Rss2Item take() throws Exception {
        return isRunning() ? queue.take() : null;
    }

    public void setRssDateFormat(Map<String, String> rssDateFormat) {
        this.rssDateFormat = rssDateFormat;
    }
}
